package org.jboss.seam.mail.ui; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Method; import java.net.URL; import javax.activation.DataHandler; import javax.activation.DataSource; import javax.activation.FileDataSource; import javax.activation.URLDataSource; import javax.faces.FacesException; import javax.faces.component.ValueHolder; import javax.faces.context.FacesContext; import javax.faces.convert.Converter; import javax.mail.MessagingException; import javax.mail.internet.MimeBodyPart; import javax.mail.util.ByteArrayDataSource; import org.jboss.seam.contexts.Contexts; import org.jboss.seam.ui.util.JSF; import org.jboss.seam.util.FacesResources; import org.jboss.seam.util.RandomStringUtils; import org.jboss.seam.util.Reflections; public class UIAttachment extends MailComponent implements ValueHolder { public class AttachmentStatus { private String contentId; public String getContentId() { return contentId; } public void setContentId(String contentId) { this.contentId = contentId; } } private Object value; private String contentType; private String fileName; private String status; private String disposition = "attachment"; public Object getValue() { if (value != null) { return value; } else { return getValue("value"); } } public void setValue(Object value) { this.value = value; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } @Override public void encodeBegin(FacesContext context) throws IOException { if (this.getChildCount() > 0) { if (Reflections.isInstanceOf(this.getChildren().get(0).getClass(), "org.jboss.seam.pdf.ui.UIDocument") || Reflections.isInstanceOf(this.getChildren().get(0).getClass(), "org.jboss.seam.excel.ui.UIWorkbook")) { Method method = Reflections.getSetterMethod(this.getChildren().get(0).getClass(), "sendRedirect"); Reflections.invokeAndWrap(method, this.getChildren().get(0), false); JSF.renderChildren(context, this); } else { setValue(encode(context).getBytes()); if (getContentType() == null) { // User hasn't specified content, assume html setContentType("text/html"); } } } } @Override public void encodeEnd(FacesContext context) throws IOException { DataSource ds = null; try { if (getValue() instanceof URL) { URL url = (URL) getValue(); ds = new URLDataSource(url); } else if (getValue() instanceof File) { File file = (File) getValue(); ds = new FileDataSource(file); } else if (getValue() instanceof String) { String string = (String) getValue(); ds = new URLDataSource( FacesResources.getResource( string, context.getExternalContext() ) ); } else if (getValue() instanceof InputStream) { InputStream is = (InputStream) getValue(); ds = new ByteArrayDataSource(is, getContentType()); } else if (getValue() != null && Reflections.isInstanceOf(getValue().getClass(), "org.jboss.seam.document.DocumentData")) { Method dataGetter = Reflections.getGetterMethod(getValue().getClass(), "data"); Method docTypeGetter = Reflections.getGetterMethod(getValue().getClass(), "documentType"); Object docType = Reflections.invokeAndWrap(docTypeGetter, getValue()); Method mimeTypeGetter = Reflections.getGetterMethod(docType.getClass(), "mimeType"); ds = new ByteArrayDataSource((byte[]) Reflections.invokeAndWrap(dataGetter, getValue()), (String) Reflections.invokeAndWrap(mimeTypeGetter, docType)); } else if (getValue() != null && getValue().getClass().isArray()) { if (getValue().getClass().getComponentType().isAssignableFrom(Byte.TYPE)) { byte[] b = (byte[]) getValue(); ds = new ByteArrayDataSource(b, getContentType()); } } if (ds != null) { // Check the DataSource is available try { ds.getInputStream(); } catch (Exception e) { if (value != null) { throw new NullPointerException("Error accessing " + value); } else { throw new NullPointerException("Error accessing " + getValueExpression("value").getExpressionString()); } } MimeBodyPart attachment = new MimeBodyPart(); // Need to manually set the contentid String contentId = RandomStringUtils.randomAlphabetic(20).toLowerCase(); if(disposition.equals("inline")) { attachment.setContentID(new Header("<" + contentId + ">").getSanitizedValue()); } attachment.setDataHandler(new DataHandler(ds)); attachment.setFileName(new Header(getName(ds.getName())).getSanitizedValue()); attachment.setDisposition(new Header(getDisposition()).getSanitizedValue()); findMessage().getAttachments().add(attachment); if (getStatus() != null) { AttachmentStatus attachmentStatus = new AttachmentStatus(); if(disposition.equals("inline")) { attachmentStatus.setContentId(contentId); } Contexts.getEventContext().set(getStatus(), attachmentStatus); } } } catch (MessagingException e) { throw new FacesException(e.getMessage(), e); } } public String getContentType() { if (contentType == null) { return getString("contentType"); } else { return contentType; } } public void setContentType(String contentType) { this.contentType = contentType; } public String getFileName() { if (fileName == null) { return getString("fileName"); } else { return fileName; } } public void setFileName(String fileName) { this.fileName = fileName; } private String removePath(String fileName) { if (fileName.lastIndexOf("/") > 0) { return fileName.substring(fileName.lastIndexOf("/") + 1); } else { return fileName; } } private String getName(String name) { if (getFileName() != null) { return getFileName(); } else { return removePath(name); } } public Converter getConverter() { return null; } public Object getLocalValue() { return value; } public void setConverter(Converter converter) { throw new UnsupportedOperationException("Cannot attach a converter to an attachment"); } public String getDisposition() { return disposition; } public void setDisposition(String disposition) { if ("attachment".equals(disposition) || "inline".equals(disposition)) { this.disposition = disposition; } } }